// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动！任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任！

using Admin.NET.Core.Service;
using Microsoft.AspNetCore.Http;
using Furion.DatabaseAccessor;
using Furion.FriendlyException;
using Mapster;
using SqlSugar;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using Admin.NET.Application.Entity;
using Admin.NET.Application.Service.BeDistributed.Dto;
using Admin.NET.Core;
using System.Linq;
using Furion.DynamicApiController;

namespace Admin.NET.Application.Service.BeDistributed;

/// <summary>
/// 库存分布服务 📊
/// </summary>
[ApiDescriptionSettings("库存分布", Name = "BeDistributed", Order = 100)]
[Route("api/beDistributed")]
public class BeDistributedService : IDynamicApiController, ITransient
{
    private readonly ISqlSugarClient _sqlSugarClient;

    public BeDistributedService(ISqlSugarClient sqlSugarClient)
    {
        _sqlSugarClient = sqlSugarClient;
    }

    /// <summary>
    /// 分页查询库存分布 📋
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("分页查询库存分布")]
    [ApiDescriptionSettings(Name = "Page"), HttpPost]
    public async Task<SqlSugarPagedList<BeDistributedStockDistributionOutput>> Page(BeDistributedStockDistributionInput input)
    {
        // 从货品表获取基本信息
        var query = _sqlSugarClient.Queryable<GoodsModel>()
            .LeftJoin<WarehouseModel>((g, w) => g.GoodsWareId == w.Id)
            .LeftJoin<WarePlaceModel>((g, w, wp) => w.Id == wp.Id)
            .WhereIF(!string.IsNullOrWhiteSpace(input.GoodsCode), (g, w, wp) => 
                g.GoodsCode.Contains(input.GoodsCode))
            .WhereIF(!string.IsNullOrWhiteSpace(input.WarehouseName), (g, w, wp) => 
                w.WareName.Contains(input.WarehouseName))
            .Select((g, w, wp) => new BeDistributedStockDistributionOutput
            {
                Id = g.Id,
                GoodsCode = g.GoodsCode,
                GoodsName = g.GoodsName,
                WarehouseName = w.WareName,
                LocationName = wp.WarePlaceName,
                StockQuantity = 0, // 将在后续计算
                StockAmount = 0, // 将在后续计算
                AvailableQuantity = 0, // 将在后续计算
                LockedQuantity = 0 // 将在后续计算
            });

        var result = await query.ToPagedListAsync(input.Page, input.PageSize);

        // 为每个货品计算库存数据
        foreach (var item in result.Items)
        {
            await CalculateStockData(item);
        }

        return result;
    }

    /// <summary>
    /// 计算库存数据
    /// </summary>
    /// <param name="item"></param>
    /// <returns></returns>
    private async Task CalculateStockData(BeDistributedStockDistributionOutput item)
    {
        // 计算入库总量
        var inboundTotal = await _sqlSugarClient.Queryable<Sysinstockorder>()
            .Where(u => u.GoodsName.Contains(item.GoodsName) && u.WarehouseName.Contains(item.WarehouseName))
            .SumAsync(u => u.InQuantity);

        // 计算出库总量
        var outboundTotal = await _sqlSugarClient.Queryable<Sysoutstockorder>()
            .Where(u => u.GoodsName.Contains(item.GoodsName) && u.WarehouseName.Contains(item.WarehouseName))
            .SumAsync(u => u.OutQuantity);

        // 计算待入库
        var pendingInbound = await _sqlSugarClient.Queryable<Syspurchaseorder>()
            .Where(u => u.GoodsName.Contains(item.GoodsName) && u.DocumentStatus == DocumentStatusEnum.Completed.ToString())
            .SumAsync(u => u.ItemQuantity);

        // 计算待出库
        var pendingOutbound = await _sqlSugarClient.Queryable<Syssalesorder>()
            .Where(u => u.GoodsName.Contains(item.GoodsName) && u.DocumentStatus == DocumentStatusEnum.Completed)
            .SumAsync(u => u.SalesQuantity);

        // 设置库存数据
        item.StockQuantity = inboundTotal - outboundTotal;
        item.AvailableQuantity = item.StockQuantity - pendingOutbound;
        item.LockedQuantity = pendingOutbound;

        // 计算库存金额 - 从货品表获取单价
        var goodsPrice = await _sqlSugarClient.Queryable<GoodsModel>()
            .Where(g => g.GoodsCode == item.GoodsCode)
            .Select(g => g.GoodsIntoMoney)
            .FirstAsync();

        if (goodsPrice.HasValue && goodsPrice > 0)
        {
            item.StockAmount = item.StockQuantity * Convert.ToDecimal(goodsPrice);
        }
    }

    /// <summary>
    /// 导出库存分布数据 📊
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("导出库存分布数据")]
    [ApiDescriptionSettings(Name = "ExportStockDistribution"), HttpPost]
    public async Task<byte[]> ExportStockDistribution(BeDistributedStockDistributionInput input)
    {
        // 获取所有库存分布数据（不分页）
        var query = _sqlSugarClient.Queryable<GoodsModel>()
            .LeftJoin<WarehouseModel>((g, w) => g.GoodsWareId == w.Id)
            .LeftJoin<WarePlaceModel>((g, w, wp) => w.Id == wp.Id)
            .WhereIF(!string.IsNullOrWhiteSpace(input.GoodsCode), (g, w, wp) => 
                g.GoodsCode.Contains(input.GoodsCode))
            .WhereIF(!string.IsNullOrWhiteSpace(input.WarehouseName), (g, w, wp) => 
                w.WareName.Contains(input.WarehouseName))
            .Select((g, w, wp) => new BeDistributedStockDistributionOutput
            {
                Id = g.Id,
                GoodsCode = g.GoodsCode,
                GoodsName = g.GoodsName,
                WarehouseName = w.WareName,
                LocationName = wp.WarePlaceName,
                StockQuantity = 0,
                StockAmount = 0,
                AvailableQuantity = 0,
                LockedQuantity = 0
            });

        var allData = await query.ToListAsync();

        // 为每个货品计算库存数据
        foreach (var item in allData)
        {
            await CalculateStockData(item);
        }

        // 这里应该使用 Excel 导出库，暂时返回空字节数组
        // 实际项目中应该使用 EPPlus 或 ClosedXML 等库来生成 Excel 文件
        return new byte[0];
    }
}
